﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GarageManagement.Converters;
using GarageManagement.DataAccess;
using GarageManagement.Models;

namespace GarageManagement.ViewModel
{
    public class CustomerViewModel : ViewModelBase
    {
        private readonly GarageManagementContext context;

        public CustomerViewModel(GarageManagementContext context)
        {
            this.context = context;
            CustomerList = GetCustomerList();
            SelectedCustomer = CustomerList.FirstOrDefault();
            CustomerTypes = GetCustomerTypes();
            SearchCommand = new RelayCommand(OnSearchCommand, CanSearch);
            NewCustomerCommand = new RelayCommand(OnCreateCustomer, () => CanCreate);
            EditCustomerCommand = new RelayCommand(OnEditCustomer, () => CanEdit);
            DeleteCustomerCommand = new RelayCommand(OnDeleteCustomer, () => CanEdit);
            SaveCommand = new RelayCommand(OnSave, () => CanSave);
            CancelCommand = new RelayCommand(OnCancel);
            SearchState = SearchState.NoSearchPerformed;
        }

        private void OnCancel()
        {
            if (SelectedCustomer.CustomerId > 0)
            {
                IsEnabled = false;
            }
            else
            {
                SelectedCustomer = new Customer();
            }
        }

        private void OnSave()
        {
            if (SelectedCustomer != null)
            {
                if (SelectedCustomer.CustomerId > 0)
                {
                    context.SaveChanges();
                }
                else
                {
                    context.Customers.Add(SelectedCustomer);

                    context.SaveChanges();

                    CustomerList.Add(SelectedCustomer);
                }

                IsEnabled = false;
            }
        }

        private void OnDeleteCustomer()
        {

        }

        private void OnEditCustomer()
        {
            IsEnabled = true;
            CanCreate = false;
        }

        private ObservableCollection<Customer> customerList;
        public ObservableCollection<Customer> CustomerList
        {
            get { return customerList; }
            set { customerList = value; RaisePropertyChanged(() => CustomerList); }
        }

        private ObservableCollection<CustomerType> customerTypes;
        public ObservableCollection<CustomerType> CustomerTypes
        {
            get { return customerTypes; }
            set { customerTypes = value; RaisePropertyChanged(() => CustomerTypes); }
        }

        private Customer selectCustomer;
        public Customer SelectedCustomer
        {
            get { return selectCustomer; }
            set
            {
                selectCustomer = value;
                RaisePropertyChanged(() => SelectedCustomer);
                IsEnabled = false;
                CanEdit = selectCustomer != null;
                CanCreate = true;
            }
        }

        private bool isEnabled;
        public bool IsEnabled
        {
            get { return isEnabled; }
            set { isEnabled = value; RaisePropertyChanged(() => IsEnabled); }
        }

        private bool canEdit;
        public bool CanEdit
        {
            get { return canEdit; }
            set { canEdit = value; RaisePropertyChanged(() => CanEdit); }
        }

        private bool canCreate = true;
        public bool CanCreate
        {
            get { return canCreate; }
            set { canCreate = value; RaisePropertyChanged(() => CanCreate); }
        }

        public bool CanSave
        {
            get
            {
                return SelectedCustomer != null &&
                       !string.IsNullOrEmpty(SelectedCustomer.Code) &&
                       !string.IsNullOrEmpty(SelectedCustomer.ContactName) &&
                       IsEnabled;
            }
        }

        public string LisencePlate { get; set; }

        public string CustomerCode { get; set; }

        public SearchState SearchState { get; set; }

        public RelayCommand SearchCommand { get; set; }

        public RelayCommand NewCustomerCommand { get; set; }

        public RelayCommand EditCustomerCommand { get; set; }

        public RelayCommand DeleteCustomerCommand { get; set; }

        public RelayCommand SaveCommand { get; set; }

        public RelayCommand CancelCommand { get; set; }

        private void OnCreateCustomer()
        {
            SelectedCustomer = new Customer { CustomerType = context.CustomerTypes.Single(x => x.CustomerTypeId == 1) };
            IsEnabled = true;
        }

        private void OnSearchCommand()
        {
            var backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += PerformSearch;
            backgroundWorker.RunWorkerCompleted += SearchComplete;
            SearchState = SearchState.Searching;
            backgroundWorker.RunWorkerAsync();
        }

        private void PerformSearch(object sender, DoWorkEventArgs eventArgs)
        {
            eventArgs.Result = GetCustomerList(LisencePlate, CustomerCode);
        }

        private void SearchComplete(object sender, RunWorkerCompletedEventArgs eventArgs)
        {
            if (SearchState == SearchState.NoSearchPerformed) return;
            if (eventArgs.Error != null) throw new Exception("Could not complete search", eventArgs.Error);

            var searchResult = eventArgs.Result as ObservableCollection<Customer>;
            if (searchResult != null && !searchResult.Any())
            {
                SearchState = SearchState.NoSearchResults;
                CustomerList = null;
            }
            else
            {
                SearchState = SearchState.SearchResultsFound;
                CustomerList = searchResult;
                SelectedCustomer = CustomerList.FirstOrDefault();
            }
        }

        private bool CanSearch()
        {
            return SearchState != SearchState.Searching;
        }

        private ObservableCollection<Customer> GetCustomerList(string lisencePlate = null, string customerCode = null)
        {
            var customerList = new ObservableCollection<Customer>();
            var query = from c in context.Customers select c;
            if (!string.IsNullOrEmpty(lisencePlate))
            {
                //TODO: implement later    
            }

            if (!string.IsNullOrEmpty(customerCode))
            {
                query = query.Where(x => x.Code.StartsWith(customerCode));
            }

            foreach (var customer in query)
            {
                customerList.Add(customer);
            }

            return customerList;
        }

        private ObservableCollection<CustomerType> GetCustomerTypes()
        {
            var typeCollection = new ObservableCollection<CustomerType>();
            var types = context.CustomerTypes.ToList();
            foreach (var type in types)
            {
                typeCollection.Add(type);
            }

            return typeCollection;
        }
    }
}
